/*
 * Config.java
 * 
 * Version information
 * 
 * Apr 8, 2006
 * 
 * Copyright (c) AmSoft Systems, 2006
 */
package net.amsoft.iservice.icontact.webapp.struts.action;

import static net.amsoft.iservice.icontact.util.IContactConstants.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.amsoft.iservice.icontact.hibernate.ContactPage;
import net.amsoft.iservice.icontact.hibernate.dataObject.LoginData;
import net.amsoft.iservice.icontact.service.IContact;
import net.amsoft.iservice.icontact.webapp.struts.form.ConfigForm;
import net.amsoft.iservice.util.exception.IServiceException;

import org.apache.log4j.Logger;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;

/**
 * Config class defines actions to configure a Contact page. An i-name can
 * create contact page which is separate or shared among more than one synonyms.
 * The contact page can be created, updated or deleted.
 * 
 * @author root
 * 
 */
public class Config extends BaseAction {
	private static Logger oLogger = Logger.getLogger(Config.class);

	@Override
	public ActionForward process(ActionMapping oMapping, ActionForm oForm,
			HttpServletRequest oRequest, HttpServletResponse oResponse)
			throws Exception {
		oLogger.info("process() : entry");
		LoginData oLoginData = (LoginData) oRequest.getSession(false)
				.getAttribute(SESSION_LOGIN_OBJ);
		if (oLoginData.isLoginStatus() == false) {
			return oMapping.findForward(FWD_CHKLOGIN);
		}
		ConfigForm oConfigForm = (ConfigForm) oForm;
		// Check if parameter is null due to direct access of page
		if (REQ_PTR_STEP_SAVE.equals(oRequest.getParameter(REQ_PTR_STEP))) {
			return save(oMapping, oConfigForm, oRequest, oLoginData);
		}
		oLogger.info("process() : Forward to :" + FWD_CHKLOGIN);
		return oMapping.findForward(FWD_CHKLOGIN);
	}

	/**
	 * Saves the configuration page to the database.
	 * 
	 * @param oMapping
	 *            Action to be taken
	 * @param oConfigForm
	 *            Form containing the contact page data
	 * @param oRequest
	 *            Current Http Request
	 * @param oLoginData
	 *            Login information
	 * @return Action
	 * @throws IServiceException
	 */
	private ActionForward save(ActionMapping oMapping, ConfigForm oConfigForm,
			HttpServletRequest oRequest, LoginData oLoginData)
			throws IServiceException {
		oLogger.info("save() : entry");
		ActionForward oFwd = null;
		try {
			ArrayList lAllSyns = oLoginData.getAllSynonyms();
			String sSynonym = oConfigForm.getSynonym();
			if (!oLoginData.getAllSynonyms().contains(sSynonym)) {
				oLogger.debug("save() : Synonym:" + sSynonym);
				sSynonym = oLoginData.getLoggedInSynonym();
			}
			ActionMessages oMsgs = new ActionErrors();

			// FIXME lastType should be stored in session
			String sLastType = oRequest.getParameter(REQ_LAST_TYPE);
			String sCurrentType = oConfigForm.getType();
			oLogger.debug("save() : CurrentType: " + sCurrentType
					+ ", LastType" + sLastType);
			if (sCurrentType.equals(TYPE_ACTIVATED_SEPARATE)) {
				oFwd = activateSeparate(oMapping, oConfigForm, sLastType);
			} else if (sCurrentType.equals(TYPE_DEACTIVATED)) {
				oMsgs = deactivate(oMapping, oConfigForm.getSynonym(),
						sLastType);
			} else if (sCurrentType.equals(TYPE_ACTIVATE_EDIT)) {
				oMsgs = editGroupPage(oMapping, oConfigForm, sLastType);
			} else {
				oFwd = activateGroup(oMapping, oConfigForm, lAllSyns, sLastType);
			}
			saveErrors(oRequest, oMsgs);
		} catch (Exception e) {
			oLogger.warn("save() : Exception: " + e.getMessage());
		}
		return oMapping.findForward(FWD_SUCCESS);
	}

	/**
	 * Used to activate a contact page. A contact page can be activated in
	 * different ways, contact page can be activated as a separate page or in a
	 * group means the contact page is shared among more than one synonyms.
	 * 
	 * @param oMapping
	 *            Actions
	 * @param oConfigForm
	 *            Configuration of contact page
	 * @param sLastType
	 *            Type of activation
	 * @return Action
	 * @throws IServiceException
	 */
	private ActionForward activateSeparate(ActionMapping oMapping,
			ConfigForm oConfigForm, String sLastType) throws IServiceException {
		oLogger.info("activateSeparate(): entry");
		if (sLastType.equals(TYPE_ACTIVATED_SEPARATE)) {
			// SEPARATE ==>> SEPARATE
			updateConfig(oConfigForm);
		} else if (sLastType.equals(TYPE_DEACTIVATED)
				|| sLastType.equals(TYPE_GROUP_ACTIVATED)) {
			// DEACTIVATED ==>> SEPARATE
			// GROUP ==>> SEPARATE
			createNew(oConfigForm);
		}
		oLogger.info("activateSeparate() : exit successfully");
		return oMapping.findForward(FWD_SUCCESS);
	}

	/**
	 * Activates a contact page in a group
	 * 
	 * @param oMapping
	 *            Action Mapping
	 * @param oConfigForm
	 *            Configuration data of contact page
	 * @param lAllSyns
	 *            List of synonyms sharing the contact page
	 * @param sLastType
	 *            Type of the activation
	 * @return Action
	 * @throws IServiceException
	 */
	private ActionForward activateGroup(ActionMapping oMapping,
			ConfigForm oConfigForm, ArrayList lAllSyns, String sLastType)
			throws IServiceException {
		oLogger.info("activateGroup() : entry");
		String sSameAsSyn = oConfigForm.getSameAsSynonyms();
		IContact.activateGroup(sSameAsSyn, lAllSyns, oConfigForm.getSynonym(),
				sLastType);
		oLogger.info("activateGroup() : exit successfully");
		return oMapping.findForward(FWD_SUCCESS);
	}

	/**
	 * Deactivates a contact page. If the contact page is shared among a group
	 * of synonyms, then contact page is deactivated for the given synonym only.
	 * 
	 * @param oMapping
	 *            Action Mapping
	 * @param sSynonym
	 *            Name of the synonym
	 * @param sLastType
	 *            Type of activation
	 * @return Action
	 * @throws IServiceException
	 */
	private ActionMessages deactivate(ActionMapping oMapping, String sSynonym,
			String sLastType) throws IServiceException {
		oLogger.info("deactivate() : entry");
		ActionMessages oMsgs = new ActionErrors();

		IContact.deactivateGroup(sLastType, sSynonym);

		if (sLastType.equals(TYPE_ACTIVATED_SEPARATE)) {
			// SEPARATE ==>> DEACTIVATED
			oMsgs.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
					MSG_CPAGE_DEACTIVATED));
		} else if (sLastType.equals(TYPE_GROUP_ACTIVATED)) {
			// GROUP ==>> DEACTIVATED
			oMsgs.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
					MSG_CPAGE_DEACTIVATED));
		}
		// nothing in case of DEACTIVATED ==>> DEACTIVATED
		oLogger.info("deactivate() : exit successfully");
		return oMsgs;
	}

	/**
	 * Method is used to edit/update an existing contact page, the contact page
	 * is activated either way if it is activated separate or in a group
	 * 
	 * @param oMapping
	 *            Action Mapping
	 * @param oConfigForm
	 *            Configuration data of contact page
	 * @param sLastType
	 *            Type of activation
	 * @return Action
	 * @throws IServiceException
	 */
	private ActionMessages editGroupPage(ActionMapping oMapping,
			ConfigForm oConfigForm, String sLastType) throws IServiceException {
		oLogger.info("editGroupPage() : entry");
		ActionMessages oMsgs = new ActionErrors();
		if (TYPE_GROUP_ACTIVATED.equals(sLastType)) {
			ContactPage oContactPage = new ContactPage();
			copyProperties(oConfigForm, oContactPage);
			IContact.editGroupPage(oConfigForm.getSynonym(), oContactPage);
			oMsgs.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
					MSG_CONF_SAVED));
		}
		oLogger.info("editGroupPage() : exit successfully");
		return oMsgs;
	}

	/**
	 * Updates new configuration data from configuration form to the contact
	 * page.
	 * 
	 * @param oConfigForm
	 *            Configuration data
	 * @throws IServiceException
	 */
	private void updateConfig(ConfigForm oConfigForm) throws IServiceException {
		oLogger.info("updateConfig() : entry");
		ContactPage oContactPage = new ContactPage();
		copyProperties(oConfigForm, oContactPage);
		IContact.updateContactPage(oConfigForm.getSynonym(), oContactPage);
		oLogger.info("updateConfig() : ContactPage updated");
	}

	/**
	 * Creates a new contact page using the data from configuration form
	 * 
	 * @param oConfigForm
	 *            Configuration data
	 * @throws IServiceException
	 */
	private void createNew(ConfigForm oConfigForm) throws IServiceException {
		oLogger.info("createNew() : entry");
		ContactPage oContactPage = new ContactPage();
		copyProperties(oConfigForm, oContactPage);
		IContact.createContactPage(oConfigForm.getSynonym(), oContactPage);
		oLogger.info("createNew(): new ContactPage created");
	}

	/**
	 * copies the properties of ConfigForm into ContactPage
	 * 
	 * @param oConfigForm
	 *            Configutiaon data for the contact page
	 * @param oContactPage
	 *            Contact page object
	 * @return Object of contact page
	 */
	private ContactPage copyProperties(ConfigForm oConfigForm,
			ContactPage oContactPage) {
		oLogger.info("copyProperties(): entry");
		oContactPage.setDisplayMsg(oConfigForm.getDisplayMsg());
		oContactPage.setDisplayName(oConfigForm.getDisplayName());
		oContactPage.setNotificationEmailMsg(oConfigForm
				.getNotificationEmailMsg());
		oContactPage.setNotificationEmailSub(oConfigForm
				.getNotificationEmailSub());
		oContactPage.setTags(oConfigForm.getTags());
		oContactPage.setVerificationEmailMsg(oConfigForm
				.getVerificationEmailMsg());
		oContactPage.setVerificationEmailSub(oConfigForm
				.getVerificationEmailSub());

		// set the notification email addresses
		String[] addresses = oConfigForm.getEmailAddresses().split("\r\n");
		for (int index = 0; index < addresses.length; index++) {
			addresses[index] = addresses[index].trim();
		}
		oContactPage.setEmail(new HashSet<String>(Arrays.asList(addresses)));

		int iVerType = oContactPage.getVerificationType();
		try {
			iVerType = Integer.parseInt(oConfigForm.getVerificationType());
			if (iVerType != VER_TYPE_EMAIL && iVerType != VER_TYPE_INAME
					&& iVerType != VER_TYPE_NONE) {
				iVerType = DEF_VER_TYPE;
			}
		} catch (Exception e) {
			oLogger.warn("copyProperties() : Received verType="
					+ oConfigForm.getVerificationType());
			oLogger.error("copyProperties() : Exception : " + e.getMessage());
		}
		oContactPage.setVerificationType(iVerType);
		return oContactPage;
	}
}
